/**
 * Copyright (c) 2018-2022, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 * 
 * Contains: interrupt manage
 * 
 * Change Logs:
 * Date           Author            Notes
 * 2021-10-31     JasonHu           Init
 */

#include <base/irq.h>
#include <base/smp.h>

#include <arch/gicv2.h>


NX_PRIVATE NX_Error NX_HalIrqUnmask(NX_IRQ_Number irqno)
{
    if (irqno < 0 || irqno >= NX_NR_IRQS)
    {
        return NX_EINVAL;
    }
    gicv2_unmask_irq(0, irqno);
    return NX_EOK;
}

NX_PRIVATE NX_Error NX_HalIrqMask(NX_IRQ_Number irqno)
{
    if (irqno < 0 || irqno >= NX_NR_IRQS)
    {
        return NX_EINVAL;
    }
    gicv2_mask_irq(0, irqno);
    return NX_EOK;
}

NX_PRIVATE NX_Error NX_HalIrqAck(NX_IRQ_Number irqno)
{
    if (irqno < 0 || irqno >= NX_NR_IRQS)
    {
        return NX_EINVAL;
    }
    gicv2_eoi_irq(0, irqno);
    return NX_EOK;
}

NX_PRIVATE void NX_HalIrqEnable(void)
{
    NX_CASM("msr    daifclr, #2": : : "memory");
}

NX_PRIVATE void NX_HalIrqDisable(void)
{
    NX_CASM("msr    daifset, #2": : : "memory");
}

NX_PRIVATE NX_UArch NX_HalIrqSaveLevel(void)
{
    NX_UArch level;
    NX_CASM("mrs    %0, daif\n\t"
            "msr    daifset, #2\n\t"
            "dsb    sy"
            : "=r"(level): : "memory");
    return level;
}

NX_PRIVATE void NX_HalIrqRestoreLevel(NX_UArch level)
{
    NX_CASM("dsb    sy\n\t"
            "msr	daif, %0\n\t"
            : :"r"(level) : "memory");
}

NX_PRIVATE NX_Bool NX_HalIrqDisabled(void)
{
    NX_UArch level;
    NX_CASM("mrs    %0, daif"
            : "=r"(level): : "memory");
    return (level & 0x80) ? NX_True : NX_False;
}

NX_INTERFACE NX_IRQ_Controller NX_IRQ_ControllerInterface = 
{
    .unmask = NX_HalIrqUnmask,
    .mask = NX_HalIrqMask,
    .ack = NX_HalIrqAck,
    .enable = NX_HalIrqEnable,
    .disable = NX_HalIrqDisable,
    .saveLevel = NX_HalIrqSaveLevel,
    .restoreLevel = NX_HalIrqRestoreLevel,
    .disabled = NX_HalIrqDisabled,
};
